<?php

namespace app\api\controller;

use app\admin\model\yexam\ComboList;
use app\admin\model\yexam\SubjectCombo;
use app\admin\model\yexam\UserCombo;
use app\common\controller\Api;
use addons\epay\library\Service;
use addons\epay\library\Wechat;
use fast\Random;
use think\addons\Controller;
use think\Hook;
use Exception;
use app\admin\model\Package;
use app\admin\model\Xorder;
use think\Db;

/**
 * @ApiSector (支付接口)
 * @ApiWeight (99999999)
 */

class Payment extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    /**
     * @ApiTitle (创建订单)
     * @ApiSummary (混合支付，请根据使用场景传入不同的参数。接口自动进行处理和生成对应的参数)
     * @ApiParams (name=tagId,type=integer,required=true,description=设备id,后台获取)
     * @ApiParams (name=device,type=string,required=false,description=设备名称)
     * @ApiParams (name=kf,type=string,required=false,description=接待的客服)
     * @ApiParams (name=redirect,type=string,reqreired=false,description=外部重定向地址)
     * @ApiParams (name=mobile,type=string,required=true,description=用户手机号)
     * @ApiParams (name=type,type=string,required=true,description=支付类型:wechat,alipay)
     * @ApiParams (name=method,type=string,required=true,description=支付方式：web,wap,app,scan,pos,mp,miniapp)
     * @ApiParams (name=product_id,type=integer,required=true,description=商品id)
     * @ApiParams (name=en_name,type=string,required=true,description=科目名称)
     * @farwish
     */
    public function create() {
        // 来源和归属,可选
        $tagId = $this->request->param('tagId',9);
        $entrySource = $this->request->param("entrySource",'');
        $list = get_platform($tagId);
        if ($entrySource == '')
            $source = $list['source'];
        else
            $source = $entrySource;
        $platform = $list['platform'];
        $device = $this->request->param('device','其它');
        $kf = $this->request->request('kf');

        // 外部自定义的重定向
        $redirect = $this->request->request('redirect');
        $mobile = $this->request->request('mobile');
        if (!$this->auth->id) {
            if (empty($mobile) || (strlen($mobile) != 11)) {
                $this->error('请填写手机号 ！');
            }
        }
        // 支付类型：wechat,alipay
        $type = $this->request->request('type');
        // 支付方法：web、wap、app、scan、pos、mp, miniapp
        $method = $this->request->request('method');
        // 产品id
        $product_id = $this->request->request('product_id',0);
        // 科目名
        $en_name = $this->request->request('en_name');

        if (!$type || !in_array($type, ['alipay', 'wechat'])) {
            $this->error("支付类型不正确");
        }
        if (!$method || !in_array($method, ['web','wap','app','scan','pos','mp','miniapp'])) {
            $this->error("支付方法不正确");
        }
        $subjectObj = \app\admin\model\yexam\Subject::get(['en_name' => $en_name]);
        if (! $subjectObj) {
            $this->error('科目不存在');
        }
        $categoryObj = \app\common\model\Category::get($subjectObj->category_id);
        if (! $categoryObj) {
            $this->error('系统分类信息有误');
        }
        $comboInfo = 0;
        if ($this->request->has('combo_id'))
        {
            $comboId = $this->request->param('combo_id'); // 套餐id
            $subjectId = $this->request->param('subjectId'); // 科目id
            $combo  = new ComboList();
            $info = $combo->where('id',$comboId)->find();
            if (!$info)
                $this->error('套餐不存在');
            $amount = $info->combo_price;
            $title = sprintf("%s - %s",$subjectObj->short_name,$info->combo_name);
            $comboInfo = json_encode(['combo_id' => $comboId,'subject_id' => $subjectId]);
        }
        else
        {
            if (empty($product_id)) {
                $this->error('缺少产品信息');
            }
            $packageObj = \app\admin\model\Package::get($product_id);
            if (! $packageObj) {
                $this->error('产品不存在');
            }
            $subject_package_ids = explode(',', $subjectObj->package_ids);
            if (! in_array($packageObj->id, $subject_package_ids)) {
                $this->error('当前科目下的没有该产品');
            }
            // 实付金额
            $amount = floatval($packageObj->price);
            // 商品名
            $title = sprintf('%s - %s', $subjectObj->short_name, $packageObj->package_name);
        }
        if (!$amount || $amount < 0) {
            $this->error("支付金额必须大于0");
        }

        // 订单号
        $out_trade_no = date("YmdHis") . uniqid();
        $order = \app\admin\model\Xorder::get(['order_no' => $out_trade_no]);
        if ($order) {
            // retry once
            $out_trade_no = date("YmdHis") . uniqid();
        }

        // 回调链接
        $notifyurl = sprintf(
            '%s/api/payment/notifyx/paytype/%s/out_trade_no/%s',
            $this->request->root(true),
            $type,
            $out_trade_no
        );

        $returnurl = sprintf(
            '%s/api/payment/returnx/paytype/%s/out_trade_no/%s/redirect/%s',
            $this->request->root(true),
            $type,
            $out_trade_no,
            $redirect
        );
        $cookieId = cookie('csmonline_cookieid');
        $client = cmf_is_mobile() ? 'm' : 'pc';
        $res = cmf_mobile_get_userId($mobile,'123456',$client,$source,$en_name,'',$cookieId);
        if(!$res) $this->error('创建用户失败');
        $user_id = $res ? $res : $this->auth->id;

        if($user_id){
            cmf_cookieId_set_userId($user_id,$cookieId);
            cmf_userId_set_cookieId($user_id,$cookieId);
        }
        // 入库
        $data = [
            'total_amount'     => floatval($amount) * 100,
            'actual_amount'     => floatval($amount) * 100,
            'order_no'          => $out_trade_no,
            'paytype'           => $type,
            'title'             => $title,
            'sale_en_name'      => $en_name,
            'sale_product_id'   => $product_id,
            'paymethod'         => $method,
            'source'            => $source,
            'platform'            => $platform,
            'device'            => $device,
            'kf'                => $kf,
            'mobile'            => $mobile,
            'user_id'           => $user_id,
            'sessionid'         => $cookieId,
            'otype'         	=> 1,
            'payment_content'   => json_encode([
                'notifyurl' => $notifyurl,
                'returnurl' => $returnurl
            ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
            "combo" => $comboInfo
        ];
        // Hook::listen('api_payment_begin', $data);
        $xorder = new \app\admin\model\Xorder;
        $xorder->data($data);
        if (! $xorder->save()) {
            $this->error('创建订单失败');
        }
        if($method == 'miniapp' && $type == 'wechat'){
            $openid = $this->request->request('openid');
            $response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method,$openid);
            return $response;
        }
        $response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method);
        //if($method == 'mp' && !$openid) $openid = Service::getOpenid();
        //$response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method, $method);
        return $response;
    }
    /**
     * @ApiTitle (创建订单，不知用途何为)
     * @ApiInternal
     * @farwish
     */
    public function createz() {
        // 来源和归属,可选
        $source = $this->request->request('source');
        $kf = $this->request->request('kf');

        // 外部自定义的重定向
        $redirect = $this->request->request('redirect');

        $mobile = $this->request->request('mobile');
        if (!$this->auth->id) {
            if (empty($mobile) || (strlen($mobile) != 11)) {
                $this->error('请填写手机号 ！');
            }
        }

        // 支付类型：wechat,alipay
        $type = $this->request->request('type');
        // 支付方法：web、wap、app、scan、pos、mp, miniapp
        $method = $this->request->request('method');
        // 科目名
        $en_name = $this->request->request('en_name');

        if (!$type || !in_array($type, ['alipay', 'wechat'])) {
            $this->error("支付类型不正确");
        }
        if (!$method || !in_array($method, ['web','wap','app','scan','pos','mp','miniapp'])) {
            $this->error("支付方法不正确");
        }
        $amount = $this->request->param('amount');  //金额
        $category_name = $this->request->param('category_name');   //栏目名称
        $package_name = $this->request->param('package_name');   //班次名称
        $category_id = $this->request->param('category_id');   //栏目id

        // 实付金额
        //$amount = floatval($packageObj->price);
        if (!$amount || $amount < 0) {
            $this->error("支付金额必须大于0");
        }

        // 商品名
        $title = sprintf('%s - %s', $category_name, $package_name);

        // 订单号
        $out_trade_no = date("YmdHis") . mt_rand(1000000, 9999999);
        $order = \app\admin\model\Xorder::get(['order_no' => $out_trade_no]);
        if ($order) {
            // retry once
            $out_trade_no = date("YmdHis") . mt_rand(1000000, 9999999);
        }

        // 回调链接
        $notifyurl = sprintf(
            '%s/api/payment/notifyx/paytype/%s/out_trade_no/%s',
            $this->request->root(true),
            $type,
            $out_trade_no
        );

        $returnurl = sprintf(
            '%s/api/payment/returnx/paytype/%s/out_trade_no/%s/redirect/%s',
            $this->request->root(true),
            $type,
            $out_trade_no,
            $redirect
        );
        $cookieId = cookie('csmonline_cookieid');
        $client = cmf_is_mobile() ? 'm' : 'pc';
        $res = cmf_mobile_get_userId($mobile,'123456',$client,$source,$en_name,'',$cookieId);
        if(!$res) $this->error('创建用户失败');
        $user_id = $res ? $res : $this->auth->id;

        if($user_id){
            cmf_cookieId_set_userId($user_id,$cookieId);
            cmf_userId_set_cookieId($user_id,$cookieId);
        }
        // 入库
        $data = [
            'total_amount'     => floatval($amount) * 100,
            'actual_amount'     => floatval($amount) * 100,
            'order_no'          => $out_trade_no,
            'paytype'           => $type,
            'title'             => $title,
            'sale_en_name'      => $en_name ? : '',
            'sale_product_id'   => $category_id,
            'paymethod'         => $method,
            'source'            => $source,
            'kf'                => $kf,
            'mobile'            => $mobile,
            'user_id'           => $user_id,
            'sessionid'         => $cookieId ? : 0,
            'otype'         	=> 2,
            'payment_content'   => json_encode([
                'notifyurl' => $notifyurl,
                'returnurl' => $returnurl
            ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
        ];
        // Hook::listen('api_payment_begin', $data);
        $xorder = new \app\admin\model\Xorder;
        $xorder->data($data);
        if (! $xorder->save()) {
            $this->error('创建订单失败');
        }

        $response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method);
        // $openid = '';
        // if($method == 'mp' && !$openid) $openid = Service::getOpenid();
        // $response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method, $method);

        return $response;
    }

    /**
     * @ApiTitle (支付成功)
     * @ApiInternal
     * @farwish
     */
    public function notifyx() {
        Db::name('test_ceshi')->insert(['time'=>time(),'content'=>'1111111']);
        $paytype = $this->request->param('paytype');
        $pay = Service::checkNotify($paytype);
        if (!$pay) {
            echo '签名错误';
            return;
        }
        $data = $pay->verify();
        try {
            $payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
            $out_trade_no = $data['out_trade_no'];
            $xorder = \app\admin\model\Xorder::get(['order_no' => $out_trade_no]);
            if ($xorder->paystatus == 1)
            {
                echo $pay->success();
                return;
            }
            if ($xorder) {
                $xorder->paystatus = 1;
                if($xorder->otype == 1){
                    //考试宝自动发码
                    $package = \app\admin\model\Package::get($xorder['sale_product_id']);
                    $vn = $package && $package['platform_vn'] ? $package['platform_vn'] : '0';
                    $ksbao = cmf_get_ksbao_sendcdk_param();
                    $url = $ksbao['domain'] . $ksbao['sendcdk'];
                    $param = [
                        "agent_code"=>$ksbao['agent_code'],
                        "secretKey"=>$ksbao['secretKey'],
                        "trade_no"=>$xorder['order_no'],
                        "username"=>$xorder['mobile'],
                        "price"=>$xorder['total_amount']/100,
                        "appename"=>$xorder['sale_en_name'],
                        "vn"=>$vn,
                    ];
                    $res = cmf_send_post($url,$param);
                    $res_array = json_decode($res,true);
                    if($res_array['code'] == 0){
                        $cdk = $res_array['data'];
                        $mobile = '';
                        if($xorder) $mobile = $xorder['mobile'];
                        if(!cmf_check_mobile($mobile)){
                            //发码成功  但是短信发送失败
                            $xorder->cdkstatus = 5;
                        }
                        $config = get_addon_config('alisms');
                        //var_dump($config);exit;
                        $sign = $config['sign'];
                        $template = $config['template']['sendCDK'];
                        $param = ['code'=>$cdk];
                        $alisms = new \addons\alisms\library\Alisms();
                        $ret = $alisms->mobile($mobile)
                            ->template($template)
                            ->sign($sign)
                            ->param($param)
                            ->send();
                        if ($ret) {
                            // $this->success("发送成功,记得保存哦,否则CDK将不会有记录");
                            //发码成功  短信发送成功
                            //echo "发码成功  短信发送成功";
                            $xorder->cdkstatus = 1;
                        } else {
                            //发码成功  但是短信发送失败
                            $xorder->cdkstatus = 5;
                        }
                        $xorder->sendtime = time();
                        $xorder->cdk = $cdk;
                    }else{
                        //发码失败
                        $xorder->cdkstatus = $res_array['code'];
                        $xorder->cdkmsg = $res_array['msg'];
                    }
                }
                if (!is_null($xorder->combo))
                {
                    $combo = json_decode($xorder->combo,true);
                    $subjectId = $combo['subject_id'];
                    $comboId = $combo['combo_id'];
                    $uid = $xorder->user_id;
                    $comboSubject = SubjectCombo::get([
                        'subject_id' => $subjectId,
                        'combo_id' => $comboId
                    ]);
                    $comboInfo = ComboList::get(['id' => $combo['combo_id']]);
                    if ($comboSubject && $comboInfo) {
                        if ($comboInfo['combo_type'] == 1){ //== 年限
                            $invalidTime = strtotime("+{$comboInfo->combo_time}year");
                        }else{ //== 考试季
                            $catId = $comboInfo->category_id;
                            $category = \app\admin\model\yexam\ComboCategory::get($catId);
                            $invalidTime = strtotime($category->exam_time);
                        }
                        $userCombo = new UserCombo();
                        $hasCombo = $userCombo->where("user_id",$uid)->where('subject_id',$subjectId)->where('pay_comboid',$comboId)->find();
                        if ($hasCombo){
                            $hasCombo->invalid_time = strtotime($hasCombo->invalid_time) + $invalidTime;
                            $hasCombo->save();
                        }else{
                            $userCombo->user_id = $uid;
                            $userCombo->subject_id = $subjectId;
                            $userCombo->invalid_time = $invalidTime;
                            $userCombo->pay_comboid = $comboId;
                            $userCombo->pay_time = time();
                            $userCombo->save();
                        }
                    }
                }
                $xorder->save();
            }
        } catch (Exception $e) {
        }
        echo $pay->success();
    }
    /**
     * @ApiTitle (获取openid)
     * @ApiInternal
     */
    public function getopenid()
    {
        $code = $this->request->request("code");//用户的登录凭证code（使用wx.login({})可获取到）这个是前端传过来

        $appid = 'wx76cd25bffa06343f';
        $secret = '0063182931dac8f8caf0326dc0f22bdf';

        $url = "https://api.weixin.qq.com/sns/jscode2session?appid=$appid&secret=$secret&js_code=$code&grant_type=authorization_code";
        $weixin = file_get_contents($url);
        if(!isset($weixin['errcode'])){
            return json(['status'=>200,'msg'=>'获取成功','data'=>$weixin]);
        }
        //$jsondecode = json_decode($weixin);
        //$array = get_object_vars($jsondecode);
        // $openid = $array['openid'];//输出openid
        //return $openid;
    }
    /**
     * @ApiTitle (支付返回)
     * @ApiInternal
     * @farwish
     */
    public function returnx() {
        $paytype = $this->request->param('paytype');
        $out_trade_no = $this->request->param('out_trade_no');

        // 外部自定义的重定向
        $redirect = $this->request->param('redirect');

        $pay = Service::checkReturn($paytype);
        if (!$pay) {
            $this->error('签名错误', '');
        }
        if(cmf_is_mobile()){
            if (isset($redirect) && $redirect) {
                $final_url = base64_decode($redirect) . '&pay_status=success';
                header("location:{$final_url}");
                return;
            }

            // header("location:https://vip.niukewang.com");
            header("location:/h5");
        }else{
            // $this->success('支付成功', url('index/user/index'));
            header("location:/index/user/xiangqing?out_trade_no=".$out_trade_no);
        }
    }
}
